﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using HtmlAgilityPack;
using System.Text.RegularExpressions;
using System.Data.Linq;
using System.IO;
using System.Net;
using System.Transactions;
using System.Threading;
using System.Configuration;
using System.ServiceModel;

namespace DataExtract
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        List<BackgroundWorker> phoneWorkers = new List<BackgroundWorker>();
        List<BackgroundWorker> keywordWorkers = new List<BackgroundWorker>();
        List<BackgroundWorker> faxWorkers = new List<BackgroundWorker>();
        bool isPhoneRunning = false;
        bool isFaxRunning = false;
        bool isKeywordRunning = false;
        List<BlockUrl> Urls = null;
        List<string> contacts = new List<string>();
        List<string> strContacts = new List<string>();
        List<int> Pages = new List<int>();
        List<BadKey> badKeys = new List<BadKey>();
        List<BadFax> badFaxes = new List<BadFax>();
        int timeOutPhoneCount = 0;
        int timeOutFaxCount = 0;
        int timeOutKeywordCount = 0;
        int caijiCount = 0;
        List<string> lstFax = new List<string>();
        

        private void frmMain_Load(object sender, EventArgs e)
        {
            cmbHour.SelectedIndex = 8;
            cmbMinute.SelectedIndex = 29;
            dgvPort.AutoGenerateColumns = false;

            using (var db = CaijiDataContext.GetDataContext()) 
            {
                db.Ports.ToList().ForEach(T => { duankous.Add(T); });
                dgvPort.DataSource = duankous;
                Urls = db.BlockUrls.ToList();
                int startId=db.HitRecords.First().SentMsgID;
                caijiCount = db.BaiduUrls.Count(T => T.ID > startId&&T.PhoneNumber!=null);

                badKeys = db.BadKeys.ToList();
                badFaxes = db.BadFaxes.ToList();
            }
            Pages.Add(2);
            Pages.Add(3);
            

            contacts.Add("contact");
            contacts.Add("lxwm");
            contacts.Add("lx.asp");
            contacts.Add("lx.htm");
            contacts.Add("lx.html");
            contacts.Add("link.html");
            contacts.Add("link.asp");
            contacts.Add("link.htm");

            strContacts.Add("联系我们");
            strContacts.Add("联系方式");

            lstFax.Add("传真");
            lstFax.Add("传&nbsp;真");
            lstFax.Add("传&#x0020;真");

            lblTotalNeed.Text = GetNeededCount().ToString();
            lblCaiji.Text = caijiCount.ToString();
            txtMsgTitle.Text = Tools.ReadSetting("MsgTitle");
        }


        BindingList<Port> duankous = new BindingList<Port>();
        private void btnAdd_Click(object sender, EventArgs e)
        {
            var form = new frmModifyPort();
            if (form.ShowDialog() == DialogResult.OK) 
            {
                duankous.Add(form.entity);

                lblTotalNeed.Text = GetNeededCount().ToString();
            }
        }

        delegate void StartClick(object sender, EventArgs e);

        private void ClearCookies()
        {
            try
            {
                foreach (string strFileName in Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.Cookies)))
                {
                    if (strFileName.ToLower().IndexOf("index.dat") == -1)
                    {
                        File.Delete(strFileName);
                    }
                }
            }
            catch
            {
                
            }
        }


        private void btnStart_Click(object sender, EventArgs e)
        {
            //TestUrl("www.globetrans.cc");


            timeOutPhoneCount = 0;
            if (InvokeRequired)
            {
                this.Invoke(new StartClick(btnStart_Click), new object[] { sender, e });
            }
            else
                if (btnStart.Text == "开始采集手机号")
                {
                    ChangeState(false);
                    btnStart.Text = "停止采集手机号";
                    isPhoneRunning = true;

                    phoneWorkers.Clear();
                    for (int i = 1; i <= numThread.Value; i++)
                    {
                        BackgroundWorker worker = new BackgroundWorker();
                        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
                        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                        phoneWorkers.Add(worker);
                    }
                    //workers[0].RunWorkerAsync();
                    phoneWorkers.ForEach(T =>
                    {
                        T.RunWorkerAsync(caijiType.Phone);
                    });
                }
                else
                {
                    ChangeState(true);
                    btnStart.Text = "开始采集手机号";
                    isPhoneRunning = false;
                }
            
        }

        void ChangeState(bool bState) 
        {
            chkPage1.Enabled = bState;
            chkPage2.Enabled = bState;
            chkPage3.Enabled = bState;
            chkPage4.Enabled = bState;
            chkPage5.Enabled = bState;
            chkPage6.Enabled = bState;
            chkPage7.Enabled = bState;
            chkPage8.Enabled = bState;

            numThread.Enabled = bState;
        }

        void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            try
            {
                caijiType type = (caijiType)e.Result;
                switch (type)
                {
                    case caijiType.Phone:
                        if (timeOutPhoneCount > 150)
                        {
                            btnStart_Click(null, null);
                            return;
                        }

                        if (!e.Cancelled && isPhoneRunning)
                        {
                            var worker = sender as BackgroundWorker;
                            worker.RunWorkerAsync(e.Result);
                        }
                        break;
                    case caijiType.Keyword:
                        if (timeOutKeywordCount > 150)
                        {
                            btnKeyword_Click(null, null);
                            return;
                        }

                        if (!e.Cancelled && isKeywordRunning)
                        {
                            var worker = sender as BackgroundWorker;
                            worker.RunWorkerAsync(e.Result);
                        }
                        break;
                    case caijiType.Fax:
                        if (timeOutFaxCount > 150)
                        {
                            btnFax_Click(null, null);
                            return;
                        }

                        if (!e.Cancelled && isFaxRunning)
                        {
                            var worker = sender as BackgroundWorker;
                            worker.RunWorkerAsync(e.Result);
                        }
                        break;

                }
                
            }
            catch { }

        }

        void TestUrl(string Url) 
        {
            HtmlWeb web = new HtmlWeb();
            HtmlAgilityPack.HtmlDocument subDoc = web.Load("http://" + Url);
            HtmlNode subNode = subDoc.DocumentNode;

            if (!SearchMobile(subNode, null))
            {
                string contact = SearchContactUrl(subNode);
                if (contact == null)
                {
                    var links = subNode.Descendants("a");
                    bool find = false;
                    foreach (HtmlNode subnd in links)
                    {
                        if (subnd.Attributes["href"] != null)
                        {
                            contact = subnd.Attributes["href"].Value.Trim();

                            foreach (String T in contacts)
                            {
                                if (contact.Contains(T))
                                {
                                    if (!contact.Contains(Url))
                                    {
                                        contact = Url + "/" + contact;
                                    }

                                    try
                                    {
                                        subDoc = web.Load("http://" + contact);
                                        subNode = subDoc.DocumentNode;
                                        timeOutPhoneCount = 0;
                                        find = true;
                                        SearchMobile(subNode, null);
                                    }
                                    catch
                                    {
                                        timeOutPhoneCount++;
                                    }
                                }
                            }
                        }

                        if (find) break;
                    }
                }
                else
                {
                    if (!contact.Contains(Url))
                    {
                        contact = Url + "/" + contact;
                    }

                    if (contact.StartsWith("http"))
                    {
                        subDoc = web.Load(contact);
                    }
                    else 
                    {
                        subDoc = web.Load("http://" + contact);
                    }
                    
                    subNode = subDoc.DocumentNode;

                    SearchMobile(subNode, null);
                }
            }
        }

        HtmlAgilityPack.HtmlDocument GetDocByUrl(string Url,caijiType type) 
        {
            switch (type)
            {
                case caijiType.Phone:
                    if (!isPhoneRunning) return null;
                    break;
                case caijiType.Keyword:
                    if (!isKeywordRunning) return null;
                    break;
                case caijiType.Fax:
                    if (!isFaxRunning) return null;
                    break;

            }
           

            HttpWebRequest req = WebRequest.Create(new Uri(Url)) as HttpWebRequest;
            req.Method = "GET";
            using (WebResponse rs = req.GetResponse())
            {
                using (Stream rss = rs.GetResponseStream())
                {
                    HttpWebResponse resp = (HttpWebResponse)rs;
                    Encoding respenc = !string.IsNullOrEmpty(resp.CharacterSet)
                                  ? Encoding.GetEncoding(resp.CharacterSet)
                                  : null;

                    HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
                    if (respenc == null)
                    {
                        doc.Load(rss);
                    }
                    else
                    {
                        doc.Load(rss, respenc);
                    }


                    return doc;
                }
            }

        }

        object phoneLockObj = new object();
        object faxLockObj = new object();
        object keywordLockObj = new object();
        Regex reg = new Regex(@"[\u4e00-\u9fa5]");
        void worker_DoWork(object sender, DoWorkEventArgs e)
        {
            caijiType type = (caijiType)e.Argument;
            try
            { 
                switch (type)
                {
                    case caijiType.Phone:
                        if (timeOutPhoneCount > 150)
                        {
                            btnStart_Click(null, null);
                            return;
                        }
                        break;
                    case caijiType.Keyword:
                        if (timeOutKeywordCount > 150)
                        {
                            btnKeyword_Click(null, null);
                            return;
                        }
                        break;
                    case caijiType.Fax:
                        if (timeOutFaxCount > 150)
                        {
                            btnFax_Click(null, null);
                            return;
                        }
                        break;

                }
                e.Result = e.Argument;

                string keyword = GetKeyword(type);

                foreach (int pageNumber in Pages) 
                {
                    HtmlAgilityPack.HtmlDocument doc = GetDocByUrl(@"http://www.baidu.com/s?wd=" + keyword + "&pn=" + pageNumber * 10, type);
                    ClearCookies();
                    HtmlNode node = doc.DocumentNode;
                    timeOutPhoneCount = 0;
                    timeOutFaxCount = 0;
                    timeOutKeywordCount = 0;

                    var nodes = node.Descendants("span");
                    foreach (HtmlNode nd in nodes)
                    {
                        if (nd.Attributes["class"] != null && nd.Attributes["class"].Value == "g")
                        {
                            try
                            {
                                string url = nd.InnerText.Trim();
                                url = url.Substring(0, url.IndexOf('/'));
                                if (!Urls.Exists(T => T.Url.Contains(url)))
                                {
                                    if (url.ToLower().Contains(".tw")) continue;
                                    if (!url.ToLower().Contains("www.")) continue;
                                    
                                    HtmlAgilityPack.HtmlDocument subDoc = null;
                                    SetCurrentUrl(url);
                                    if (url.StartsWith("http"))
                                    {
                                        subDoc = GetDocByUrl(url, type);
                                    }
                                    else
                                    {
                                        subDoc = GetDocByUrl("http://" + url, type);
                                    }

                                    HtmlNode subNode = subDoc.DocumentNode;
                                    timeOutPhoneCount = 0;
                                    timeOutFaxCount = 0;
                                    timeOutKeywordCount = 0;

                                    if (type == caijiType.Keyword) 
                                    {
                                        lock (keywordLockObj) 
                                        {
                                            using (var db = CaijiDataContext.GetDataContext()) 
                                            {
                                                var titles = subNode.Descendants("title");

                                                if (titles != null && titles.Count() > 0)
                                                {
                                                    string title = titles.First().InnerText;

                                                    string[] keywords = title.Split(new char[] { ',', '，', '|', ' ', '-', '—', '_', '/', '、', '\\' });

                                                    for (int i = 0; i < keywords.Length - 2; i++)
                                                    {
                                                        string kd = keywords[i];
                                                        if (string.IsNullOrEmpty(kd)) continue;
                                                        kd = kd.Trim();

                                                        if (kd.Length >= 10 || kd.Length < 2) continue;

                                                        if (!reg.IsMatch(kd)) continue;

                                                        bool isBad = false;
                                                        for (int j = 0; j < badKeys.Count; j++)
                                                        {
                                                            BadKey bk = badKeys[j];
                                                            if (bk.Type == "通配")
                                                            {
                                                                if (kd.Contains(bk.BadName))
                                                                {
                                                                    isBad = true;
                                                                    break;
                                                                }
                                                            }
                                                            else if (bk.Type == "精确")
                                                            {
                                                                if (kd == bk.BadName)
                                                                {
                                                                    isBad = true;
                                                                    break;
                                                                }
                                                            }
                                                            else
                                                            {
                                                                if (kd.StartsWith(bk.BadName))
                                                                {
                                                                    isBad = true;
                                                                    break;
                                                                }
                                                            }
                                                        }

                                                        if (isBad) continue;

                                                        if (!db.Keywords.Any(T => T.StringKeyword.Trim() == kd.Trim()))
                                                        {
                                                            Keyword keywordObj = new Keyword();
                                                            keywordObj.StringKeyword = kd.Trim();
                                                            keywordObj.DateTime = DateTime.Now;
                                                            db.Keywords.InsertOnSubmit(keywordObj);
                                                        }
                                                    }
                                                }

                                                db.SubmitChanges();
                                            }

                                            continue;
                                        }
                                    }
                                    else if (type == caijiType.Phone)
                                    {
                                        BaiduUrl urlObj = new BaiduUrl();
                                        lock (phoneLockObj)
                                        {
                                            using (var db = CaijiDataContext.GetDataContext())
                                            {
                                                if (db.BaiduUrls.Any(T => T.Url.Contains(url))) continue;

                                                urlObj.Url = url;
                                                urlObj.DateTime = DateTime.Now;
                                                urlObj.KeywordName = keyword;
                                                db.BaiduUrls.InsertOnSubmit(urlObj);
                                                db.SubmitChanges();
                                            }
                                        }

                                        if (!SearchMobile(subNode, urlObj))
                                        {
                                            string contact = SearchContactUrl(subNode);
                                            if (contact == null)
                                            {
                                                var links = subNode.Descendants("a");
                                                bool find = false;
                                                foreach (HtmlNode subnd in links)
                                                {
                                                    if (subnd.Attributes["href"] != null)
                                                    {
                                                        contact = subnd.Attributes["href"].Value.Trim();

                                                        foreach (String T in contacts)
                                                        {
                                                            if (contact.Contains(T))
                                                            {
                                                                if (!contact.Contains(url))
                                                                {
                                                                    contact = url + "/" + contact;
                                                                }

                                                                try
                                                                {
                                                                    if (contact.StartsWith("http"))
                                                                    {
                                                                        subDoc = GetDocByUrl(contact, type);
                                                                    }
                                                                    else
                                                                    {
                                                                        subDoc = GetDocByUrl("http://" + contact, type);
                                                                    }
                                                                    subNode = subDoc.DocumentNode;
                                                                    timeOutPhoneCount = 0;
                                                                    timeOutFaxCount = 0;
                                                                    timeOutKeywordCount = 0;
                                                                    find = true;
                                                                    SearchMobile(subNode, urlObj);
                                                                }
                                                                catch
                                                                {
                                                                    switch (type)
                                                                    {
                                                                        case caijiType.Phone:
                                                                            timeOutPhoneCount++;
                                                                            break;
                                                                        case caijiType.Keyword:
                                                                            timeOutKeywordCount++;
                                                                            break;
                                                                        case caijiType.Fax:
                                                                            timeOutFaxCount++;
                                                                            break;
                                                                    } 
                                                                }
                                                            }
                                                        }
                                                    }

                                                    if (find) break;
                                                }
                                            }
                                            else
                                            {
                                                if (!contact.Contains(url))
                                                {
                                                    contact = url + "/" + contact;
                                                }

                                                if (contact.StartsWith("http"))
                                                {
                                                    subDoc = GetDocByUrl(contact, type);
                                                }
                                                else
                                                {
                                                    subDoc = GetDocByUrl("http://" + contact, type);
                                                }
                                                subNode = subDoc.DocumentNode;

                                                SearchMobile(subNode, urlObj);
                                            }
                                        }
                                    }
                                    else if (type == caijiType.Fax) 
                                    {
                                        if (!SearchFax(subNode,keyword,url))
                                        {
                                            string contact = SearchContactUrl(subNode);
                                            if (contact == null)
                                            {
                                                var links = subNode.Descendants("a");
                                                bool find = false;
                                                foreach (HtmlNode subnd in links)
                                                {
                                                    if (subnd.Attributes["href"] != null)
                                                    {
                                                        contact = subnd.Attributes["href"].Value.Trim();

                                                        foreach (String T in contacts)
                                                        {
                                                            if (contact.Contains(T))
                                                            {
                                                                if (!contact.Contains(url))
                                                                {
                                                                    contact = url + "/" + contact;
                                                                }

                                                                try
                                                                {
                                                                    if (contact.StartsWith("http"))
                                                                    {
                                                                        subDoc = GetDocByUrl(contact, type);
                                                                    }
                                                                    else
                                                                    {
                                                                        subDoc = GetDocByUrl("http://" + contact, type);
                                                                    }
                                                                    subNode = subDoc.DocumentNode;
                                                                    timeOutPhoneCount = 0;
                                                                    timeOutFaxCount = 0;
                                                                    timeOutKeywordCount = 0;
                                                                    find = true;
                                                                    SearchFax(subNode, keyword, url);
                                                                }
                                                                catch
                                                                {
                                                                    switch (type)
                                                                    {
                                                                        case caijiType.Phone:
                                                                            timeOutPhoneCount++;
                                                                            break;
                                                                        case caijiType.Keyword:
                                                                            timeOutKeywordCount++;
                                                                            break;
                                                                        case caijiType.Fax:
                                                                            timeOutFaxCount++;
                                                                            break;
                                                                    }
                                                                }
                                                            }
                                                        }
                                                    }

                                                    if (find) break;
                                                }
                                            }
                                            else
                                            {
                                                if (!contact.Contains(url))
                                                {
                                                    contact = url + "/" + contact;
                                                }

                                                if (contact.StartsWith("http"))
                                                {
                                                    subDoc = GetDocByUrl(contact, type);
                                                }
                                                else
                                                {
                                                    subDoc = GetDocByUrl("http://" + contact, type);
                                                }
                                                subNode = subDoc.DocumentNode;

                                                SearchFax(subNode, keyword, url);
                                            }
                                        }
                                    }
                                }
                            }
                            catch
                            {
                                switch (type)
                                {
                                    case caijiType.Phone:
                                        timeOutPhoneCount++;
                                        break;
                                    case caijiType.Keyword:
                                        timeOutKeywordCount++;
                                        break;
                                    case caijiType.Fax:
                                        timeOutFaxCount++;
                                        break;
                                }
                            }
                        }
                    }
                }                
            }
            catch
            {
                switch (type)
                {
                    case caijiType.Phone:
                        timeOutPhoneCount++;
                        break;
                    case caijiType.Keyword:
                        timeOutKeywordCount++;
                        break;
                    case caijiType.Fax:
                        timeOutFaxCount++;
                        break;
                }
            }

        }

        bool SearchMobile(HtmlNode subNode, BaiduUrl urlObj) 
        {
            bool findPhone = false;

            string strPhone = FindPhone(subNode);
            if (strPhone != "")
            {
                findPhone = true;
                using (var db = CaijiDataContext.GetDataContext())
                {
                    var phones = strPhone.Split('|');
                    foreach (string phone in phones)
                    {
                        if (!string.IsNullOrEmpty(phone)&&phone.Length==11&&!db.BaiduUrls.Any(T => T.PhoneNumber == phone))
                        {
                            if (urlObj != null)
                            {
                                urlObj.PhoneNumber = phone;
                                db.BaiduUrls.Attach(urlObj);
                                db.Refresh(RefreshMode.KeepCurrentValues, urlObj);
                                db.SubmitChanges(ConflictMode.ContinueOnConflict);

                                caijiCount++;
                                SetTotalCaiji(caijiCount);
                            }                           

                            break;
                        }
                    }
                }
            }

            return findPhone;
        }

        bool SearchFax(HtmlNode subNode,string keyword,string Url)
        {
            bool findPhone = false;

            string strPhone = FindFax(subNode);
            if (strPhone != "")
            {
                findPhone = true;
                using (var db = CaijiDataContext.GetDataContext())
                {
                    var phones = strPhone.Split('|');
                    Fax fax = new Fax();
                    foreach (string phone in phones)
                    {
                        if (!string.IsNullOrEmpty(phone) && !db.Faxes.Any(T => T.FaxNumber == phone))
                        {
                            fax.FaxNumber = phone;
                            fax.DateTime = DateTime.Now;
                            fax.KeywordName = keyword;
                            fax.Url = Url;
                            db.Faxes.InsertOnSubmit(fax);
                            db.SubmitChanges(ConflictMode.ContinueOnConflict);

                            break;
                        }
                    }
                }                
            }

            return findPhone;
        }

        string SearchContactUrl(HtmlNode subNode)
        {
            string strUrl=null;
            foreach(String S in strContacts)
            {
                Stack<HtmlNode> tempStack = new Stack<HtmlNode>();

                bool find = subNode.InnerText.Contains(S);
                HtmlNode tempNode = subNode;
                while (find)
                {
                    if (tempNode.ChildNodes.Count > 0)
                    {
                        bool first = true;
                        foreach (HtmlNode subnd in tempNode.ChildNodes)
                        {
                            if (subnd.InnerText.Contains(S))
                            {
                                if (first)
                                {
                                    tempNode = subnd;
                                }
                                else
                                    tempStack.Push(subnd);

                            }
                        }
                    }
                    else
                    {
                        strUrl = FindUrl(tempNode, 3);
                        if (strUrl != null)
                        {                            
                            break;
                        }
                        else
                        {
                            if (tempStack.Count > 0)
                            {
                                tempNode = tempStack.Pop();
                            }
                            else
                            {
                                break;
                            }
                        }
                    }
                }

                if (strUrl != null)
                {
                    break;
                }
            }

            return strUrl;
        }

        string phoneReg = "[1][3|5|8]\\d{9}";
        string strChars = @"1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM.";
        private string FindPhone(HtmlNode node) 
        {
            string innerText = node.InnerText;      
            var matches = Regex.Matches(innerText, phoneReg);
            string phoneNo = "";
            foreach (Match m in matches) 
            {
                int startIndex = innerText.IndexOf(m.Value);
                if (innerText.Length > startIndex + 11)
                {
                    string last = innerText.Substring(startIndex + 11, 1);
                    if (!strChars.Contains(last))
                    {
                        phoneNo += m.Value + "|";
                    }
                }
                else 
                {
                    phoneNo += m.Value + "|";
                }
            }

            return phoneNo;
        }

        string faxReg = "0510-\\d{8}";
        private string FindFax(HtmlNode node)
        {
            string phoneNo = "";
            string innerText = node.InnerText;
            lstFax.ForEach(F => 
            {
                int startIndex = innerText.IndexOf(F);
                if (startIndex > 0) 
                {
                    innerText = innerText.Substring(startIndex,50);

                    var matches = Regex.Matches(innerText, faxReg);
                    foreach (Match m in matches)
                    {
                        string[] faxes = m.Value.Split('-');
                        bool isBad = false;
                        for (int i = 0; i < badFaxes.Count; i++) 
                        {
                            if (faxes[1].StartsWith(badFaxes[i].FaxNumber)) 
                            {
                                isBad = true;
                                break;
                            }
                        }

                        if (isBad) break;

                        startIndex = innerText.IndexOf(m.Value);
                        if (innerText.Length > startIndex + m.Length)
                        {
                            string last = innerText.Substring(startIndex + m.Length, 1);
                            if (!strChars.Contains(last))
                            {
                                phoneNo += m.Value + "|";
                            }
                        }
                        else
                        {
                            phoneNo += m.Value + "|";
                        }
                    }
                }                
            });
            

            return phoneNo;
        }

        private string FindUrl(HtmlNode node, int Upper)
        {
            if (Upper <= 0) return null;

            if (node.Name == "a")
            {
                return node.Attributes["href"].Value;
            }
            else
            {
                return FindUrl(node.ParentNode, Upper - 1);                
            }
        }

        object lockOjb = new object();
        string GetKeyword(caijiType type) 
        {
            string keywordName = null;
            //lock (lockOjb) 
            {
                using (CaijiDataContext db = CaijiDataContext.GetDataContext())
                {
                    db.spGetKeyword((int)type, ref keywordName);
                }
            }

            //string keywordName = KeywordService.GetKeywork((int)type);
            SetCurrentKeyword(keywordName);
            return keywordName;        
            
        }        

        private void dgvPort_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            if (dgvPort.Columns[e.ColumnIndex].Name == "colEdit")
            {
                Port key = dgvPort.Rows[e.RowIndex].DataBoundItem as Port;
                var frm = new frmModifyPort(key);
                if (frm.ShowDialog() == DialogResult.OK)
                {
                    foreach (Port dk in duankous) 
                    {
                        if (dk.ID == frm.entity.ID) 
                        {
                            dk.PortName = frm.entity.PortName;
                            dk.SendFile = frm.entity.SendFile;
                            dk.MaxNum = frm.entity.MaxNum;
                            dk.Enabled = frm.entity.Enabled;
                            break;
                        }
                    }

                    lblTotalNeed.Text = GetNeededCount().ToString();
                }
            }
            else if (dgvPort.Columns[e.ColumnIndex].Name == "colDelete")
            {
                if (MessageBox.Show("你确认要删除吗", "删除", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                {
                    Port key = dgvPort.Rows[e.RowIndex].DataBoundItem as Port;
                    using (var db = CaijiDataContext.GetDataContext())
                    {
                        db.Ports.DeleteAllOnSubmit(db.Ports.Where(T => T.ID == key.ID));
                        db.SubmitChanges();
                        for (int i = 0; i < duankous.Count; i++) 
                        {
                            if (duankous[i].ID == key.ID) 
                            {
                                duankous.RemoveAt(i);
                                break;
                            }
                        }

                        lblTotalNeed.Text = GetNeededCount().ToString();
                    }
                }
            }
            else if (dgvPort.Columns[e.ColumnIndex].Name == "colImport")
            {
                if (MessageBox.Show("你确认要导入吗", "导入", MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes)
                {
                    Port key = dgvPort.Rows[e.RowIndex].DataBoundItem as Port;
                    ExportToCat(key);
                }
            }
            else if (dgvPort.Columns[e.ColumnIndex].Name == "colEnable") 
            {
                dgvPort.EndEdit();
            }
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void btnExport_Click(object sender, EventArgs e)
        {
            ExportToCat(null);
        }

        private void chkExport_CheckedChanged(object sender, EventArgs e)
        {
            if (chkExport.Checked) 
            {
                if (txtMsgTitle.Text.Trim() == "") 
                {
                    MessageBox.Show("请输入短信标题");
                }
            }
        }

        int totalNeedCount = 0;
        int GetNeededCount() 
        {
            int Count = 0;
            foreach (DataGridViewRow  row in this.dgvPort.Rows) 
            {
                Port port = row.DataBoundItem as Port;
                if (port.Enabled) 
                {
                    Count += (port.MaxNum-port.OutMessage);
                }
            }

            totalNeedCount = Count;
            return Count;
        }

        void SetCurrentKeyword(string keyword) 
        {
            if (InvokeRequired)
            {
                Invoke(new Action<string>(SetCurrentKeyword), new string[] { keyword });
            }
            else
            {
                lblKeyword.Text= keyword; 
            }
        }

        void SetCurrentUrl(string Url)
        {
            if (InvokeRequired)
            {
                Invoke(new Action<string>(SetCurrentUrl), new string[] { Url });
            }
            else
            {
                lblUrl.Text = Url;
            }
        }

        void SetTotalCaiji(int Count) 
        {
            if (InvokeRequired)
            {
                Invoke(new Action<int>(SetTotalCaiji), new object[] { Count });
            }
            else 
            {
                lblCaiji.Text = Count.ToString();

                
                if (chkExport.Checked && Count >= totalNeedCount) 
                {
                    btnStart_Click(null, null);
                    ExportToCat(null);
                }
            }
        }

        private void chkPage1_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox chk = sender as CheckBox;
            int i = Convert.ToInt32(chk.Name.Substring(chk.Name.Length - 1));
            if (chk.Checked)
            {
                if (!Pages.Contains(i))
                {
                    Pages.Add(i);
                }
            }
            else 
            {
                if (Pages.Contains(i)) 
                {
                    Pages.Remove(i);
                }
            }
        }

        void ExportToCat(Port single) 
        {
            try
            {
                if(!btnExport.Enabled) return;

                btnExport.Enabled = false;
                btnExport.Text = "导入中，请稍候";
                Application.DoEvents();
                
                using (MasterDataContext master = MasterDataContext.GetDataContext())
                {
                    using (CaijiDataContext db = CaijiDataContext.GetDataContext())
                    {
                        var record = db.HitRecords.First();
                        if (single == null)
                        {
                            int minute = 0;
                            foreach (DataGridViewRow row in dgvPort.Rows)
                            {
                                Port port = row.DataBoundItem as Port;
                                int i = port.OutMessage;
                                bool bFirst = true;
                                
                                if (port.Enabled&&i<port.MaxNum)
                                {
                                    while (i < port.MaxNum)
                                    {
                                        if (bFirst && i + 4 > port.MaxNum) break;
                                        if (!bFirst && i + 15 > port.MaxNum) break;

                                        List<BaiduUrl> baidus = null;
                                        if (bFirst)
                                        {
                                            bFirst = false;
                                            baidus = db.ExecuteQuery<BaiduUrl>("select top 4 * from tbBaiduUrl where ID>" + record.SentMsgID + " and PhoneNumber is not null and PhoneNumber<>'' order by ID").ToList();
                                            if (baidus.Count < 4) break;
                                        }
                                        else
                                        {
                                            baidus = db.ExecuteQuery<BaiduUrl>("select top 15 * from tbBaiduUrl where ID>" + record.SentMsgID + " and PhoneNumber is not null and PhoneNumber<>'' order by ID").ToList();
                                            if (baidus.Count < 15) break;
                                        }

                                        string phones = "";
                                        foreach (BaiduUrl bu in baidus)
                                        {
                                            phones += "," + bu.PhoneNumber;
                                            record.SentMsgID = bu.ID;
                                            i++;
                                            caijiCount--;
                                        }

                                        MSG_Outbox outbox = new MSG_Outbox();
                                        outbox.ExpressLevel = 1;
                                        outbox.Sender = "10086";
                                        outbox.Receiver = phones.Remove(0, 1);
                                        outbox.MsgType = 1;
                                        outbox.MsgTitle = txtMsgTitle.Text;
                                        outbox.MMSContentLocation = port.SendFile;
                                        if (baidus.Count == 4)

                                            if (chkSystemDate.Checked)
                                                outbox.SendTime = DateTime.Now.Date.AddHours(cmbHour.SelectedIndex + 1).AddMinutes(cmbMinute.SelectedIndex + 1 + minute);
                                            else
                                                outbox.SendTime = dtSend.Value.Date.AddHours(cmbHour.SelectedIndex + 1).AddMinutes(cmbMinute.SelectedIndex + 1 + minute);

                                        else
                                            outbox.SendTime = new DateTime(2020, 12, 12, 9, 30, 0);
                                        outbox.CommPort = port.PortName;

                                        master.MSG_Outboxes.InsertOnSubmit(outbox);
                                        master.SubmitChanges();
                                        db.SubmitChanges();
                                        
                                    }

                                    minute += 2;
                                }
                            }
                        }
                        else 
                        {
                            Port port = single;
                            if (port.Enabled && port.OutMessage < port.MaxNum)
                            {
                                int i = port.OutMessage;
                                bool bFirst = true;
                                while (i < port.MaxNum)
                                {
                                    if (bFirst && i + 4 > port.MaxNum) break;
                                    if (!bFirst && i + 15 > port.MaxNum) break;

                                    List<BaiduUrl> baidus = null;
                                    if (bFirst)
                                    {
                                        baidus = db.ExecuteQuery<BaiduUrl>("select top 4 * from tbBaiduUrl where ID>" + record.SentMsgID + " and PhoneNumber is not null and PhoneNumber<>'' order by ID").ToList();
                                        bFirst = false;
                                        if (baidus.Count < 4) break;
                                    }
                                    else
                                    {
                                        baidus = db.ExecuteQuery<BaiduUrl>("select top 15 * from tbBaiduUrl where ID>" + record.SentMsgID + " and PhoneNumber is not null and PhoneNumber<>'' order by ID").ToList();
                                        if (baidus.Count < 15) break;
                                    }

                                    string phones = "";
                                    foreach (BaiduUrl bu in baidus)
                                    {
                                        phones += "," + bu.PhoneNumber;
                                        record.SentMsgID = bu.ID;
                                        i++;
                                        caijiCount--;
                                    }

                                    MSG_Outbox outbox = new MSG_Outbox();
                                    outbox.ExpressLevel = 1;
                                    outbox.Sender = "10086";
                                    outbox.Receiver = phones.Remove(0, 1);
                                    outbox.MsgType = 1;
                                    outbox.MsgTitle = txtMsgTitle.Text;
                                    outbox.MMSContentLocation = port.SendFile;
                                    if (baidus.Count == 4)
                                        if(chkSystemDate.Checked)
                                            outbox.SendTime = DateTime.Now.Date.AddHours(cmbHour.SelectedIndex + 1).AddMinutes(cmbMinute.SelectedIndex + 1);
                                        else
                                            outbox.SendTime = dtSend.Value.Date.AddHours(cmbHour.SelectedIndex + 1).AddMinutes(cmbMinute.SelectedIndex + 1);
                                    else
                                        outbox.SendTime = new DateTime(2020, 12, 12, 9, 30, 0);
                                    outbox.CommPort = port.PortName;

                                    master.MSG_Outboxes.InsertOnSubmit(outbox);
                                    master.SubmitChanges();
                                    db.SubmitChanges();
                                }
                            }
                        }
                        
                    }
                }
            }
            finally 
            {
                lblCaiji.Text = caijiCount.ToString();
                lblTotalNeed.Text = GetNeededCount().ToString();
                this.dgvPort.Refresh();
                btnExport.Enabled = true;
                btnExport.Text = "导入短信猫";
            }                        
        }

        private void btnKeyword_Click(object sender, EventArgs e)
        {
            timeOutKeywordCount = 0;
            if (InvokeRequired)
            {
                this.Invoke(new StartClick(btnKeyword_Click), new object[] { sender, e });
            }
            else
                if (btnKeyword.Text == "开始采集关键字")
                {
                    btnKeyword.Text = "停止采集关键字";
                    isKeywordRunning = true;

                    keywordWorkers.Clear();
                    for (int i = 0; i <= numThread.Value; i++)
                    {
                        BackgroundWorker worker = new BackgroundWorker();
                        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
                        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                        keywordWorkers.Add(worker);
                    }
                    //keywordWorkers[0].RunWorkerAsync(caijiType.Keyword);
                    keywordWorkers.ForEach(T =>
                    {
                        T.RunWorkerAsync(caijiType.Keyword);
                    });
                }
                else
                {
                    btnKeyword.Text = "开始采集关键字";
                    isKeywordRunning = false;
                }
        }

        private void dgvPort_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            Port entity = dgvPort.Rows[e.RowIndex].DataBoundItem as Port;
            using (var db = CaijiDataContext.GetDataContext())
            {
                db.Ports.Attach(entity);
                db.Refresh(RefreshMode.KeepCurrentValues, entity);
                db.SubmitChanges();               

                lblTotalNeed.Text = GetNeededCount().ToString();
            }
        }

        private void btnFax_Click(object sender, EventArgs e)
        {
            timeOutFaxCount = 0;
            if (InvokeRequired)
            {
                this.Invoke(new StartClick(btnFax_Click), new object[] { sender, e });
            }
            else
                if (btnFax.Text == "开始采集传真")
                {
                    btnFax.Text = "停止采集传真";
                    isFaxRunning = true;

                    faxWorkers.Clear();
                    for (int i = 0; i <= numThread.Value; i++)
                    {
                        BackgroundWorker worker = new BackgroundWorker();
                        worker.DoWork += new DoWorkEventHandler(worker_DoWork);
                        worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
                        faxWorkers.Add(worker);
                    }
                    //faxWorkers[0].RunWorkerAsync(caijiType.Fax);
                    faxWorkers.ForEach(T =>
                    {
                        T.RunWorkerAsync(caijiType.Fax);
                    });
                }
                else
                {
                    btnFax.Text = "开始采集传真";
                    isFaxRunning = false;
                }
        }

        private void txtMsgTitle_Leave(object sender, EventArgs e)
        {
            Tools.ChangeSetting("MsgTitle", txtMsgTitle.Text.Trim());
        }

        private void chkSystemDate_CheckedChanged(object sender, EventArgs e)
        {
            if (chkSystemDate.Checked)
            {
                dtSend.Enabled = false;
            }
            else 
            {
                dtSend.Enabled = true;
            }
        }

        private void tmDate_Tick(object sender, EventArgs e)
        {
            if (!chkCheckTime.Checked&&dtSend.Value.Date != DateTime.Now.Date) 
            {
                dtSend.Value = DateTime.Now.Date;
                Application.DoEvents();
            }
            
        }
    }

    enum caijiType 
    {
        Phone=1,
        Fax=3,
        Keyword=2
    }
}
